<?php

	namespace org\tekuna\core\configuration;


	/**
	 * Abstract class that represents every node of a configuration. Every node has
	 * an aspect in that it lives (some kind of namespace), a name and a value. This
	 * class contains all necessary getters and setters and enforces the implementation
	 * of a meaningful __toString() method.
	 */
	abstract class ConfigurationNode {

		/** the fields to store the node's attributes */
		protected
			$sAspect = '',
			$sName = '',
			$sValue = '';


		/**
		 * Construct a new ConfigurationNode using the aspect, name and value of the node
		 *
		 * @param string $sAspect the aspect of the node (e.g. core)
		 * @param string $sName the name of the node (e.g. testelement)
		 * @param string $sValue the value of the element (this is mostly empty)
		 */
		public function __construct($sAspect, $sName, $sValue) {

			$this -> setAspect($sAspect);
			$this -> setName($sName);
			$this -> setValue($sValue);
		}


		/**
		 * This declaration enforces the meaningful implementation of a __toString()
		 * method of the concrete implementations of this abstract class. The goal is
		 * to print the whole configuration by calling __toString() on the root node.
		 */
		abstract function __toString();


		/**
		 * Set the node's aspect
		 *
		 * @param string $sAspect the aspect
		 */
		public function setAspect($sAspect) {

			$this -> sAspect = $sAspect;
		}

		/**
		 * get the node's aspect
		 *
		 * @return string the aspect
		 */
		public function getAspect() {

			return $this -> sAspect;
		}

		/**
		 * Set the node's name
		 *
		 * @param string $sName the name
		 */
		public function setName($sName) {

			$this -> sName = $sName;
		}

		/**
		 * get the node's name
		 *
		 * @return string the name
		 */
		public function getName() {

			return $this -> sName;
		}

		/**
		 * Set the node's value
		 *
		 * @param string $sValue the value
		 */
		public function setValue($sValue) {

			$this -> sValue = $sValue;
		}

		/**
		 * get the node's value
		 *
		 * @return string the value
		 */
		public function getValue() {

			return $this -> sValue;
		}

		/**
		 * get the node's value as of type boolean.
		 *
		 * @return boolean the value
		 * @throws ConfigurationException if the value cannot be converted to boolean
		 */
		public function getValueAsBoolean() {

			// truncate value
			$sBoolValue = strtolower(trim($this -> getValue()));

			// recognize true
			if ($sBoolValue === 'true') {

				return true;
			}

			// recognize false
			if ($sBoolValue === 'false') {

				return false;
			}

			// value no boolean
			throw new ConfigurationException("Could not interpret value '". $this -> getValue() ."' as boolean on ConfigurationNode ". trim($this -> __toString()));
		}

		/**
		 * get the node's value as of type integer
		 *
		 * @return integer the value as integer
		 */
		public function getValueAsInteger() {

			return (int) $this -> getValue();
		}

		/**
		 * get the node's value as of type float
		 *
		 * @return integer the value as float
		 */
		public function getValueAsFloat() {

			return (float) $this -> getValue();
		}
	}
